#include "DELAY.h"

DELAY_T* DELAY_t;



//************************************
// Method:    	CALCU_SAMA						//< SAMA运算函数
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	bool							//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	float dt						//< 运算周期
// Parameter: 	bool * DI						//< 数字量输入值数组指针
// Parameter: 	bool * DO						//< 数字量输出值数组指针
// Parameter: 	bool * AI						//< 模拟量输入值数组指针
// Parameter: 	bool * AO						//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(DELAY)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
	int AllDelayStep = 0;

	/****************变量定义区开始**************/
	/*<<<<<定义输入变量>>>>>*/
	float defAI;
	float Time_Delay;		                  //< 纯迟延时间

	/*<<<<<定义输出变量>>>>>*/
	float Output_Value;

	/*<<<<<定义参数变量>>>>>*/
	float Init_Value;			              //< 初始值

	/*<<<<<定义中间变量>>>>>*/
	int* Time_Sum;                            //< 记录当前迟延步数	             
	int* Index;                               //< 标记输入数据在占暂存数组中位置
	float* TimeNotAchievedHoldValue;		  //< Shike20210506 延迟时间未达到上位设置的时间，需要保持引脚输出的数值
	bool* Flag_TimeNotAchievedHoldValue;	  //< Shike20210506 延迟时间未达到上位设置的时间，需要保持引脚输出的标志位
	int* TimeNotAchievedIndexMemory;		  //< Shike20210506 记录延迟时间改变一瞬间Index的位置
	int* LastAllDelayStep;					  //< Shike20210506
	int* TimeNotAchievedAllDelayStepMemory;	  //< Shike20210506
	float* Mid[DELAY_TIME_ARRAY];             //< 输入数据暂存数组

	/****************变量定义区结束**************/

	NAME(DELAY)* Obj = (NAME(DELAY)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	defAI = AI[0];
	Time_Delay = AI[1];

	/*<<<<<参数变量赋值>>>>>*/
	Init_Value = Obj->Par.Init_Value;

	/*<<<<<中间变量赋值>>>>>*/
	Time_Sum = &(Obj->Sta.Time_Sum);
	Index = &(Obj->Sta.Index);
	TimeNotAchievedHoldValue = &(Obj->Sta.TimeNotAchievedHoldValue);
	Flag_TimeNotAchievedHoldValue = &(Obj->Sta.Flag_TimeNotAchievedHoldValue);
	TimeNotAchievedIndexMemory = &(Obj->Sta.TimeNotAchievedIndexMemory);
	LastAllDelayStep = &(Obj->Sta.LastAllDelayStep);
	TimeNotAchievedAllDelayStepMemory = &(Obj->Sta.TimeNotAchievedAllDelayStepMemory);
	for (int k = 0; k < DELAY_TIME_ARRAY; k++)
		Mid[k] = &(Obj->Sta.Mid[k]);

	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/

	if (Time_Delay > DELAY_TIME_ARRAY * dt)							//< 纯迟延时间限值		duan0903 最大延时时间为20秒	      
		Time_Delay = DELAY_TIME_ARRAY * dt;

	AllDelayStep = (unsigned short)(Time_Delay / dt);				//< 纯迟延总步数

	if (Time_Sum[0] < AllDelayStep)									//< 未到时间 
	{
		if (Flag_TimeNotAchievedHoldValue[0] == false)				//< Shike20210506 未到延迟时间的第一步会进入这个判断
		{
			Flag_TimeNotAchievedHoldValue[0] = true;				//< Shike20210506 未到延迟时间的第一步先将标志位置1防止再次进入
			TimeNotAchievedHoldValue[0] = Obj->Base.Out.Last_AO[0];	//< Shike20210506 记录未到延迟时间时模块输出需要保持的数值
			TimeNotAchievedIndexMemory[0] = Index[0];				//< Shike20210506 记录延迟时间改变一瞬间Index的位置
			Output_Value = TimeNotAchievedHoldValue[0];				//< Shike20210506 输出为存储的保持的值
			TimeNotAchievedAllDelayStepMemory[0] = LastAllDelayStep[0];			//< Shike20210506 
		}
		else
			Output_Value = TimeNotAchievedHoldValue[0];				//< Shike20210506 未到延迟时间除第一步以外都直接让输出等于存储的保持的值。
		Index[0] = Time_Sum[0];
		Mid[Index[0]][0] = defAI;									//< 放入新的数据（Time_Sum[0] > DelayStep满足后，在取出数据的位置放进新的数据）
		Time_Sum[0]++;												//< 记录当前步数
		//< Shike20210506 ********************************************************************
		if ((Time_Sum[0] == AllDelayStep) && (TimeNotAchievedIndexMemory[0] > 0))
		{
			float OutTemp[DELAY_TIME_ARRAY];						//< Shike20210506 用来调整顺序的数组
			for (int i = TimeNotAchievedIndexMemory[0]; i < TimeNotAchievedAllDelayStepMemory[0]; i++)
				OutTemp[i - TimeNotAchievedIndexMemory[0]] = Mid[i][0];
			for (int i = 0; i < TimeNotAchievedIndexMemory[0]; i++)
				OutTemp[i + (TimeNotAchievedAllDelayStepMemory[0] - TimeNotAchievedIndexMemory[0])] = Mid[i][0];
			for (int i = TimeNotAchievedAllDelayStepMemory[0]; i < DELAY_TIME_ARRAY; i++)
				OutTemp[i] = Mid[i][0];
			for (int i = 0; i < DELAY_TIME_ARRAY; i++)
				Mid[i][0] = OutTemp[i];
		}
		//< Shike20210506 ********************************************************************
	}
	else															//< 到达时间
	{
		TimeNotAchievedHoldValue[0] = 0;							//< Shike20210506
		Flag_TimeNotAchievedHoldValue[0] = false;					//< Shike20210506 需要将标志位恢复0，以准备当迟延时间这个参数变大时再次进入上面未到时间的判断
		TimeNotAchievedIndexMemory[0] = 0;							//< Shike20210506 未到延迟时间Index记录清零
		if (LastAllDelayStep[0] > AllDelayStep)						//< Shike20210506 延迟时间发生变化且上一时刻延迟时间更大，重新排列数组
		{
			if (Index[0] >= AllDelayStep)							//< Shike20210506 变化时Index在AllDelayStep往后的位置，只需要重排前面的AllDelayStep个
			{
				float OutTemp[DELAY_TIME_ARRAY];					//< Shike20210506 用来调整顺序的数组
				for (int i = 0; i < AllDelayStep; i++)
					OutTemp[i] = Mid[i + (Index[0] - AllDelayStep)][0];
				for (int i = 0; i < AllDelayStep; i++)
					Mid[i][0] = OutTemp[i];
				for (int i = AllDelayStep; i < DELAY_TIME_ARRAY; i++)
					Mid[i][0] = 0;
			}
			else                                                    //< Shike20210506 变化时Index在AllDelayStep往后的位置，只需要重排前面的AllDelayStep个
			{
				float OutTemp[DELAY_TIME_ARRAY];
				for (int i = 0; i < AllDelayStep - Index[0]; i++)
					OutTemp[i] = Mid[i + (DELAY_TIME_ARRAY - (AllDelayStep - Index[0]))][0];
				for (int i = AllDelayStep - Index[0]; i < AllDelayStep; i++)
					OutTemp[i] = Mid[i - (AllDelayStep - Index[0])][0];
				for (int i = 0; i < AllDelayStep; i++)
					Mid[i][0] = OutTemp[i];
				for (int i = AllDelayStep; i < DELAY_TIME_ARRAY; i++)
					Mid[i][0] = 0;
			}
			Index[0] = 0;
		}
		if (AllDelayStep <= 0)
			Index[0] = 0;
		else
			Index[0] = Index[0] % AllDelayStep;						//< 核心

		Output_Value = Mid[Index[0]][0];							//< 将达到纯迟延时间的数据取出
		Mid[Index[0]][0] = defAI;									//< 放入新的数据（Time_Sum[0] > DelayStep满足后，在取出数据的位置放进新的数据）
		Time_Sum[0]++;												//< 记录当前步数
	}

	if (Time_Sum[0] >= AllDelayStep)
	{
		Time_Sum[0] = AllDelayStep;
		Index[0]++;
	}
	LastAllDelayStep[0] = AllDelayStep;
	/********************************************/
	/**************算法功能实现结束**************/
	/********************************************/

	/****************运算结果输出**************/
	AO[0] = Output_Value;
	//< printf("纯迟延模块的输出值为%f \r\n", AO[0]);			duan0827


	/**************运算结果输出完毕************/
	return true;
}



//************************************
// Method:    	BCPARA							//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(DELAY)(Model_Base_t* arg, void** Data)
{
	NAME(DELAY)* Obj = (NAME(DELAY)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA							//< 备份SAMA运算中间参数
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 指定模块类型链表的指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(DELAY)(Model_Base_t* arg, void** Data)
{
	NAME(DELAY)* Obj = (NAME(DELAY)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA							//< 解析备份的SAMA运算中间参数
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	int								//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(DELAY)(Model_Base_t* arg, void** Data)
{
	NAME(DELAY)* Obj = (NAME(DELAY)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR				//< 在线修改模块参数函数
// Programmer:  duan
// Time:		2019/03/17
// Returns:   	int						//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg		//< 指定模块类型链表的指针
// Parameter: 	void** Data				//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(DELAY)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(DELAY)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR						//< 初始化模块运算中间参数
// Programmer:  duan
// Time:		2019/03/17
// Parameter: 	Model_Base_t* arg				//< 模块参数结构体指针
//************************************
void INIT_STAPAR(DELAY)(Model_Base_t* arg)
{
	NAME(DELAY)* name = (NAME(DELAY)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/

	/**************对中间变量结构体的相关参数进行赋值结束************/
}
